#include "storage_engine.h"
#include "disk_manager.h"
#include "utils/logger.h"
#include "buffer-pool.h"
#include "replacer.h"
#include "LRU-replacer.h"
#include "simple_wal.h" //新增：包含极简WAL日志管理器定义
#include <stdexcept>
#include <iostream>

// 实现类定义（只在cpp文件中可见）
class StorageEngine::Impl {
public:
     /*
    @param db_name 数据库名称，用于创建数据文件（如："./data/mydatabase"）
    @param buffer_pool_size 缓存池大小（页数），默认1024页（如4KB/页则为4MB缓存）
     */
    Impl(const std::string& db_name, size_t buffer_pool_size)
        : db_name_(db_name), buffer_pool_size_(buffer_pool_size),
        stop_flush_thread_(false) {
        // 初始化数据库文件、缓存池等资源
        // 这里只是示例，实际应有文件打开、缓存分配等逻辑

        stats_ = CacheStats{};
        //初始化磁盘管理器
        std::string db_file_path = "data/" + db_name;  //确保文件存放在data目录
        LOG_INFO("数据库文件路径: " + db_file_path);
        disk_manager_ = std::make_unique<DiskManager>(db_file_path, db_name + ".meta");
        page_count_ = disk_manager_->get_page_count();
        LOG_INFO("当前数据库页数: " + std::to_string(page_count_));


        // 注意：replacer 的最大容量通常是 buffer_pool_size
        // 在 disk_manager_ 创建之后，继续初始化 buffer_pool_manager_  参数匹配，需要replacer实例
        buffer_pool_manager_ = std::make_unique<BufferPoolManager>(buffer_pool_size_, 
                                                        std::make_unique<LRUReplacer>(buffer_pool_size_),
                                                        disk_manager_.get());

        // 新增：初始化WAL（在磁盘管理器之后）
        // wal_file_path_ = "data/" + db_name + ".wal";
        // wal_manager_ = std::make_unique<SimpleWAL>(wal_file_path_);
        // LOG_INFO("WAL初始化成功: " + wal_file_path_);
        
        // // 新增：从WAL恢复数据（在缓冲池初始化之后）
        // recover_from_wal();


        // 新增：启动后台刷页线程（绑定刷页函数）
        background_flush_thread_ = std::thread(&StorageEngine::Impl::background_flush_func, this);
        LOG_INFO_F("Background flush thread started (interval: %lu ms)", flush_interval_ms_);

        
            
    }

    ~Impl() {

        // 步骤1：设置停止标志，唤醒线程
        stop_flush_thread_ = true;
        flush_cv_.notify_one(); // 唤醒休眠的线程，让它检查停止标志

        // 步骤2：等待线程执行完毕（避免线程资源泄漏）
        if (background_flush_thread_.joinable()) {
            background_flush_thread_.join();
            LOG_INFO("Background flush thread stopped");
        }
        // 析构时写回所有脏页，释放资源
        flush_all_pages();
    }

    page_id_t allocate_page() {
         // 调用磁盘管理器分配新页
        page_id_t new_page_id = disk_manager_->allocate_page();
        if (new_page_id != INVALID_PAGE_ID) {
            ++page_count_; // 可选：同步统计信息
        }
        return new_page_id;

    }

    //释放页
    bool free_page(page_id_t page_id) {
       // 1. 参数校验
    if (page_id == 0) {
        LOG_ERROR("Cannot free reserved page 0");
        return false;
    }

    // 2. 调用 DiskManager 释放该页（加入空闲链表）
    if (disk_manager_->free_page(page_id)) {
        // ✅ 正确：这里不要改 page_count_
        // 可选：你可以维护一个统计值，如 num_allocated_pages_
        // 但 page_count_ 是文件大小，不能动！
        LOG_DEBUG_F("Page %d freed successfully ", page_id);
        return true;
    }

    LOG_ERROR_F("Failed to free page %d", page_id);
    return false;
    }

    //读取特定页
    std::shared_ptr<Page> read_page(page_id_t page_id) {
       // 1. 统计：总请求数 +1
    stats_.total_requests++;

    // 2. 通过缓冲池获取页（内部会查缓存）
     // FetchPage 返回 Page*
    Page* page_ptr = buffer_pool_manager_->FetchPage(page_id);

    if (page_ptr != nullptr) {
        // 3. 缓存命中：页已在内存或成功从磁盘加载
        stats_.cache_hits++;
        // ✅ 安全包装：创建 shared_ptr，但不接管删除
        // 当 shared_ptr 析构时，不会 delete page_ptr
        return std::shared_ptr<Page>(
            std::shared_ptr<Page>{},  // 空的 shared_ptr（不拥有资源，仅共享控制块）
            page_ptr                  // 实际指向的 Page 对象
        );
    } else {
        // 4. 缓存未命中：且无法从磁盘加载（如文件损坏、page_id 越界）
        stats_.cache_misses++;
        // 可选：记录日志
        LOG_ERROR_F("Failed to load page %d", page_id);
        return nullptr; //失败返回null
    }

    }

    bool write_page(const std::shared_ptr<Page>& page) {
        if (!page) return false;
        
        // 新增的WAL写入代码（添加在最前面）
        if (wal_manager_ && page->get_data()) {
            wal_manager_->LogPageUpdate(
                page->get_page_id(),
                page->get_data(),
                PAGE_SIZE
            );
        }
        
        // 原有代码完全不变
        page->mark_dirty();
        
        return true;
    }

    std::shared_ptr<Page> get_page(page_id_t page_id) {
        // 等同于read_page
        return read_page(page_id);
    }
     

      //刷特定页
    bool flush_page(page_id_t page_id) {
        // 1. 严格校验 page_id 合法性（排除无效页和保留页）
    if (page_id == INVALID_PAGE_ID || page_id < 1) {
        LOG_ERROR_F("Invalid page_id: %d (must be >=1 and not INVALID)", page_id);
        return false;
    }

    // 2. 核心：通过缓冲池管理器完成刷页（所有细节由 BufferPoolManager 封装）
    // 这里直接复用之前在 BufferPoolManager 中实现的 FlushPage 接口
    bool flush_success = buffer_pool_manager_->FlushPage(page_id);

    // 3. 根据刷页结果更新统计和日志
    if (flush_success) {
        // 注意：stats_.disk_writes 仅统计“实际写入磁盘”的次数
        // （BufferPoolManager::FlushPage 仅在刷脏页成功时返回 true，可安全累加）
        stats_.disk_writes++;
        LOG_DEBUG_F("Page %d flushed successfully (disk writes: %d)", 
                    page_id, stats_.disk_writes);
        return true;
    } else {
        // 这里通过日志区分不同场景（需 BufferPoolManager::FlushPage 补充详细日志）
        LOG_WARNING_F("Failed to flush page %d (possible reasons: not in buffer pool / not dirty / disk error)", 
                   page_id);
        return true;
    }
    }

      //刷所有脏页
    void flush_all_pages() {
       // 1. 校验缓冲池管理器是否初始化（避免空指针访问）
    if (!buffer_pool_manager_) {
        LOG_ERROR("BufferPoolManager is not initialized, cannot flush all pages");
        return;
    }

    // 2. 核心：调用缓冲池管理器的 FlushAllPages，获取实际刷回的脏页数
    // （需先修改 BufferPoolManager::FlushAllPages，让其返回“实际写入磁盘的脏页数”）
    size_t actual_flushed_count = buffer_pool_manager_->FlushAllPages();

    // 3. 正确更新统计：仅累加“实际写入磁盘”的次数（而非总页数）
    stats_.disk_writes += actual_flushed_count;

    // 4. 日志记录：明确刷页结果（总页数、实际刷回数、当前统计值）
    LOG_INFO_F("Flush all dirty pages completed: "
               "total pages in buffer pool = %d, "
               "actual flushed dirty pages = %d, "
               "total disk writes = %d",
               buffer_pool_manager_->GetPageCount(),  // 缓冲池中已分配的页数
               actual_flushed_count,
               stats_.disk_writes);
    }

    // 在Impl类中新增这个私有方法
    void recover_from_wal() {
        LOG_INFO("开始WAL恢复...");
        size_t recovered_count = 0;
        
        auto apply_callback = [this, &recovered_count](page_id_t page_id, const char* data, size_t size) {
            auto page = buffer_pool_manager_->FetchPage(page_id);
            if (page) {
                size_t copy_size = std::min(size, static_cast<size_t>(PAGE_SIZE));
                std::memcpy(page->get_data(), data, copy_size);
                page->mark_dirty();
                recovered_count++;
            }
        };
        
        if (wal_manager_) {
            wal_manager_->Recover(apply_callback);
            LOG_INFO("WAL恢复完成，恢复了 " + std::to_string(recovered_count) + " 个页面");
        }
    }


    CacheStats cache_stats() const {
        return stats_;
    }

    void reset_stats() {
        stats_ = CacheStats{};
    }

    void set_replacement_policy(bool use_lru) {
        use_lru_ = use_lru;
    }

    //有问题
    size_t get_page_count() const {
        return page_count_;
    }

    size_t get_buffer_pool_size() const {
        return buffer_pool_size_;
    }

private:
    std::string db_name_;
    size_t buffer_pool_size_;
    size_t page_count_;
    CacheStats stats_;
    bool use_lru_ = true;
    std::unique_ptr<DiskManager> disk_manager_; // 新增磁盘管理器成员
    std::unique_ptr<BufferPoolManager> buffer_pool_manager_;//新增缓冲池管理器成员
    std::unique_ptr<Replacer> replacer_;  // 替换算法实例
    // 新增WAL相关成员
    std::unique_ptr<SimpleWAL> wal_manager_;
    std::string wal_file_path_;
    
    // 新增私有方法
    // void init_wal();
    // void recover_from_wal();

    // 新增：后台刷页线程相关成员
    std::thread background_flush_thread_;    // 后台刷页线程
    std::mutex flush_mutex_;                  // 保护脏页访问的互斥锁
    std::condition_variable flush_cv_;        // 控制线程休眠/唤醒
    std::atomic<bool> stop_flush_thread_;     // 线程停止标志（原子变量，线程安全）
    const size_t flush_interval_ms_ =10000;   // 刷页间隔（5秒，可调整）
    // 新增：后台线程的核心刷页函数（内部调用，不对外暴露）
    void background_flush_func();
};



void StorageEngine::Impl::background_flush_func() {
    // std::cout << "Background flush thread started." << std::endl;
    
    // 线程主循环：未收到停止信号则持续运行
    // 用 load() 读取原子变量，明确且安全
    while (!stop_flush_thread_.load(std::memory_order_relaxed)) {
        std::unique_lock<std::mutex> lock(flush_mutex_);
        // LOG_INFO("Background flush thread started.");
        
        // 显式捕获 this，通过 this 访问成员变量，避免复制
        flush_cv_.wait_for(
            lock,
            std::chrono::milliseconds(flush_interval_ms_),
            [this]() { 
                // 读取时指定内存序（relaxed 足够，无需强内存序）
                return stop_flush_thread_.load(std::memory_order_relaxed); 
            }
        );

        // 再次检查，避免虚假唤醒
        if (stop_flush_thread_.load(std::memory_order_relaxed)) {
            break;
        }

        // 3. 遍历所有有效页ID，筛选出脏页并刷回磁盘
        // （注：page_count_ 是你 Impl 类中存储的“当前数据库总页数”，需确保其正确更新）
        size_t flushed_count = 0;  // 记录成功刷回的脏页数
        size_t total_dirty = 0;    // 记录总脏页数（用于日志）

        // 加锁保护 buffer_pool_manager_ 的访问（避免与前台操作冲突）
        // std::lock_guard<std::mutex> pool_lock(buffer_pool_manager_->latch_);

        // 遍历所有可能的页ID（0 ~ page_count_ - 1，确保不越界）
        for (page_id_t page_id = 1; page_id <= page_count_; ++page_id) {
            // 3.1 检查该页是否在缓冲池中，且是脏页（利用 BufferPoolManager 现有接口）
            if (buffer_pool_manager_->IsDirty(page_id)) {
                total_dirty++;
                // 3.2 刷回脏页（调用 BufferPoolManager 自带的 FlushPage）
                if (buffer_pool_manager_->FlushPage(page_id)) {
                    flushed_count++;
                } else {
                    LOG_INFO_F("Background flush: failed to flush page %d", page_id);
                }
            }
        }

        // 4. 打印刷页日志（可选，便于调试和监控）
        // if (total_dirty > 0) {
        //     LOG_INFO_F("Background flush completed: %lu/%lu dirty pages flushed (interval: %lu ms)",
        //                flushed_count, total_dirty, flush_interval_ms_);
        // } else {
        //     LOG_DEBUG("Background flush: no dirty pages to flush");
        // }
    }

    // LOG_INFO("Background flush thread exited normally");
}
// StorageEngine 构造与析构
StorageEngine::StorageEngine(const std::string& db_name, size_t buffer_pool_size)
    : impl_(std::make_unique<Impl>(db_name, buffer_pool_size)) {}

StorageEngine::~StorageEngine() = default;

// 所有接口直接转发给 impl_
page_id_t StorageEngine::allocate_page() {
    return impl_->allocate_page();
}

bool StorageEngine::free_page(page_id_t page_id) {
    return impl_->free_page(page_id);
}

std::shared_ptr<Page> StorageEngine::read_page(page_id_t page_id) {
    return impl_->read_page(page_id);
}

bool StorageEngine::write_page(const std::shared_ptr<Page>& page) {
    // return impl_->write_page(page,offset,data);
    return impl_->write_page(page);
}

std::shared_ptr<Page> StorageEngine::get_page(page_id_t page_id) {
    return impl_->get_page(page_id);
}

bool StorageEngine::flush_page(page_id_t page_id) {
    return impl_->flush_page(page_id);
}

void StorageEngine::flush_all_pages() {
    impl_->flush_all_pages();
}

CacheStats StorageEngine::cache_stats() const {
    return impl_->cache_stats();
}

void StorageEngine::reset_stats() {
    impl_->reset_stats();
}

void StorageEngine::set_replacement_policy(bool use_lru) {
    impl_->set_replacement_policy(use_lru);
}

size_t StorageEngine::get_page_count() const {
    return impl_->get_page_count();
}

size_t StorageEngine::get_buffer_pool_size() const {
    return impl_->get_buffer_pool_size();
}

